/******************************************************************************
	Cobalt - utility libraries for building XNA games
	Copyright (C) 2008 Philip Djonov

	This program is free software; you can redistribute it and/or modify it
	under the terms of the GNU General Public License as published by the Free
	Software Foundation; either version 2 of the License, or (at your option)
	any later version.

	This program is distributed in the hope that it will be useful, but
	WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
	or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
	for more details.

	You should have received a copy of the GNU General Public License along
	with this program; if not, write to the
	
		Free Software Foundation, Inc.
		51 Franklin Street, Fifth Floor
		Boston, MA  02110-1301, USA.
******************************************************************************/

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Content.Pipeline;

namespace Cobalt.Content.Pipeline.Quake
{
	public sealed class QuakeTokenizer : IContentTokenizer
	{

		#region Token Parsing

		private void SkipWhiteSpace( string line, ref int idx )
		{
			while( idx < line.Length && char.IsWhiteSpace( line[idx] ) )
				idx++;
		}

		private string ParseFixedToken( string line, ref int idx, int len )
		{
			string ret = line.Substring( idx, len );
			idx += len;
			return ret;
		}

		private string ParseToken( string line, ref int idx, Predicate<char> isTokenChar )
		{
			int len;
			for( len = 1; idx + len < line.Length; len++ )
			{
				if( !isTokenChar( line[idx + len] ) )
					break;
			}

			return ParseFixedToken( line, ref idx, len );
		}

		private string ParseStringLiteral( string line, ref int idx )
		{
			char quote = line[idx];

			int len;
			for( len = 1; idx + len < line.Length; len++ )
			{
				if( line[idx + len] == quote && line[idx + len - 1] != '\\' )
					break;
			}

			if( idx + len == line.Length )
				throw new InvalidContentException( "Unexpected newline or end of file in string literal." );

			string ret = line.Substring( idx + 1, len - 1 );

			idx += len + 1;
			return ret;
		}

		public string ParseToken( string line, ref int idx )
		{
			SkipWhiteSpace( line, ref idx );

			char ch = line[idx];

			if( ch == '\'' || ch == '\"' )
				return ParseStringLiteral( line, ref idx );

			if( !char.IsWhiteSpace( ch ) )
				return ParseToken( line, ref idx, delegate( char c ) { return !char.IsWhiteSpace( c ); } );			

			throw new InvalidContentException( "Unable to parse token." );
		}

		#endregion
	}
}